/**********************************************************************************************************************
 * \file LinkLayerComm.c
 * \brief 以太网链路层中断通信实现
 * \description 基于GETH模块实现的以太网链路层中断通信功能
 *********************************************************************************************************************/

#include "LinkLayerComm.h"
#include <string.h>
#include "ConfigurationIsr.h"

/* 全局变量 */
static LinkLayerComm g_linkLayerComm;

/**
 * \brief 初始化链路层通信模块
 * \param gethDriver GETH驱动句柄
 * \return TRUE: 初始化成功, FALSE: 初始化失败
 */
boolean LinkLayerComm_init(IfxGeth_Eth *gethDriver)
{
    if (gethDriver == NULL) {
        return FALSE;
    }

    /* 初始化全局状态 */
    memset(&g_linkLayerComm, 0, sizeof(LinkLayerComm));
    g_linkLayerComm.gethDriver = gethDriver;
    g_linkLayerComm.txInIndex = 0;
    g_linkLayerComm.txOutIndex = 0;
    g_linkLayerComm.rxCount = 0;
    g_linkLayerComm.rxCallback = NULL;
    g_linkLayerComm.initialized = TRUE;

    /* 配置中断源 */
    /* 接收中断配置 - 使用IfxGeth_ServiceRequest_6 + 通道号 */
    volatile Ifx_SRC_SRCR *rxSrcSFR = IfxGeth_getSrcPointer(gethDriver->gethSFR, 
        (IfxGeth_ServiceRequest)((uint32)IfxGeth_ServiceRequest_6 + (uint32)IfxGeth_RxDmaChannel_0));
    IfxSrc_init(rxSrcSFR, IfxSrc_Tos_cpu0, ISR_PRIORITY_GETH_RX);
    IfxSrc_enable(rxSrcSFR);
    
    /* 发送中断配置 - 使用IfxGeth_ServiceRequest_2 + 通道号 */
    volatile Ifx_SRC_SRCR *txSrcSFR = IfxGeth_getSrcPointer(gethDriver->gethSFR, 
        (IfxGeth_ServiceRequest)((uint32)IfxGeth_ServiceRequest_2 + (uint32)IfxGeth_TxDmaChannel_0));
    IfxSrc_init(txSrcSFR, IfxSrc_Tos_cpu0, ISR_PRIORITY_GETH_TX);
    IfxSrc_enable(txSrcSFR);
    
    /* 清除可能存在的中断标志 */
    IfxGeth_dma_clearInterruptFlag(gethDriver->gethSFR, IfxGeth_DmaChannel_0, IfxGeth_DmaInterruptFlag_receiveInterrupt);
    IfxGeth_dma_clearInterruptFlag(gethDriver->gethSFR, IfxGeth_DmaChannel_0, IfxGeth_DmaInterruptFlag_transmitInterrupt);

    /* 启用接收和发送中断 */
    IfxGeth_dma_enableInterrupt(gethDriver->gethSFR, IfxGeth_DmaChannel_0, IfxGeth_DmaInterruptFlag_receiveInterrupt);
    IfxGeth_dma_enableInterrupt(gethDriver->gethSFR, IfxGeth_DmaChannel_0, IfxGeth_DmaInterruptFlag_transmitInterrupt);

    return TRUE;
}

/**
 * \brief 发送以太网帧
 * \param data 要发送的数据指针
 * \param length 数据长度(不包含CRC)
 * \param destMac 目标MAC地址
 * \param type 以太网类型
 * \return 发送状态
 */
LinkLayerTxStatus LinkLayerComm_sendFrame(uint8* data, uint32 length, uint8* destMac, uint16 type)
{
    if (!g_linkLayerComm.initialized || data == NULL || destMac == NULL) {
        return LINKLAYER_TX_STATUS_ERROR;
    }

    /* 检查长度是否合法 */
    if (length > (LINKLAYER_MAX_FRAME_SIZE - 14)) { /* 14字节MAC头 */
        return LINKLAYER_TX_STATUS_ERROR;
    }

    /* 获取当前输入缓冲区索引 */
    uint32 currentInIndex = g_linkLayerComm.txInIndex;
    uint8* txBuffer = g_linkLayerComm.txBuffers[currentInIndex];

    /* 构造以太网帧头 */
    // 目标MAC地址
    memcpy(txBuffer, destMac, 6);
    
    // 源MAC地址(从GETH寄存器读取)
    Ifx_GETH *gethSFR = g_linkLayerComm.gethDriver->gethSFR;
    uint32 macAddrLow = gethSFR->MAC_ADDRESS_LOW0.U;
    uint32 macAddrHigh = gethSFR->MAC_ADDRESS_HIGH0.U;
    
    txBuffer[6] = (uint8)(macAddrLow & 0xFF);              // MAC[0]
    txBuffer[7] = (uint8)((macAddrLow >> 8) & 0xFF);       // MAC[1]
    txBuffer[8] = (uint8)((macAddrLow >> 16) & 0xFF);      // MAC[2]
    txBuffer[9] = (uint8)((macAddrLow >> 24) & 0xFF);      // MAC[3]
    txBuffer[10] = (uint8)(macAddrHigh & 0xFF);            // MAC[4]
    txBuffer[11] = (uint8)((macAddrHigh >> 8) & 0xFF);     // MAC[5]
    
    // 以太网类型(大端序)
    txBuffer[12] = (uint8)((type >> 8) & 0xFF);
    txBuffer[13] = (uint8)(type & 0xFF);

    /* 复制数据 */
    memcpy(&txBuffer[14], data, length);

    /* 计算帧总长度 */
    uint32 frameLength = 14 + length; /* 14字节MAC头 + 数据长度 */

    /* 尝试立即发送 */
    uint8* ethTxBuffer = IfxGeth_Eth_getTransmitBuffer(g_linkLayerComm.gethDriver, IfxGeth_TxDmaChannel_0);
    if (ethTxBuffer != NULL) {
        /* 复制帧数据到GETH发送缓冲区 */
        memcpy(ethTxBuffer, txBuffer, frameLength);
        
        /* 发送帧 */
        IfxGeth_Eth_sendTransmitBuffer(g_linkLayerComm.gethDriver, frameLength, IfxGeth_TxDmaChannel_0);
        
        /* 更新输入索引 */
        g_linkLayerComm.txInIndex = (g_linkLayerComm.txInIndex + 1) % LINKLAYER_TX_BUFFER_COUNT;
        
        return LINKLAYER_TX_STATUS_OK;
    } else {
        /* 发送缓冲区忙，更新索引等待处理 */
        g_linkLayerComm.txInIndex = (g_linkLayerComm.txInIndex + 1) % LINKLAYER_TX_BUFFER_COUNT;
        return LINKLAYER_TX_STATUS_BUSY;
    }
}

/**
 * \brief 注册接收回调函数
 * \param callback 回调函数指针
 */
void LinkLayerComm_registerRxCallback(LinkLayerRxCallback callback)
{
    g_linkLayerComm.rxCallback = callback;
}

/**
 * \brief 处理发送缓冲区中的数据
 */
void LinkLayerComm_processTxBuffer(void)
{
    if (!g_linkLayerComm.initialized) {
        return;
    }

    /* 检查是否有等待发送的数据 */
    if (g_linkLayerComm.txInIndex != g_linkLayerComm.txOutIndex) {
        /* 尝试获取发送缓冲区 */
        uint8* ethTxBuffer = IfxGeth_Eth_getTransmitBuffer(g_linkLayerComm.gethDriver, IfxGeth_TxDmaChannel_0);
        if (ethTxBuffer != NULL) {
            /* 由于我们没有存储帧长度信息，这里简化处理
             * 实际应用中应该维护一个帧长度数组或使用更复杂的缓冲区管理 */
            // 假设帧长度不超过最大值
            uint32 frameLength = LINKLAYER_MAX_FRAME_SIZE;
            
            /* 复制数据到GETH发送缓冲区 */
            memcpy(ethTxBuffer, g_linkLayerComm.txBuffers[g_linkLayerComm.txOutIndex], frameLength);
            
            /* 发送帧 */
            IfxGeth_Eth_sendTransmitBuffer(g_linkLayerComm.gethDriver, frameLength, IfxGeth_TxDmaChannel_0);
            
            /* 更新输出索引 */
            g_linkLayerComm.txOutIndex = (g_linkLayerComm.txOutIndex + 1) % LINKLAYER_TX_BUFFER_COUNT;
        }
    }
}

/**
 * \brief 处理接收到的以太网帧
 */
void LinkLayerComm_processRxFrame(void)
{
    if (!g_linkLayerComm.initialized) {
        return;
    }

    /* 循环处理所有接收到的帧 */
    while (IfxGeth_Eth_isRxDataAvailable(g_linkLayerComm.gethDriver, IfxGeth_RxDmaChannel_0) != FALSE) {
        /* 获取接收缓冲区 */
        uint8* rxBuffer = IfxGeth_Eth_getReceiveBuffer(g_linkLayerComm.gethDriver, IfxGeth_RxDmaChannel_0);
        
        if (rxBuffer != NULL) {
            /* 获取接收描述符以获取帧长度 */
            IfxGeth_RxDescr* rxDescriptor = (IfxGeth_RxDescr*)IfxGeth_Eth_getActualRxDescriptor(
                g_linkLayerComm.gethDriver, IfxGeth_RxDmaChannel_0);
            
            /* 计算帧长度 */
            uint32 frameLength = 0;
            if (rxDescriptor != NULL) {
                frameLength = ((rxDescriptor->RDES1.U & 0x3FFF0000) >> 16);
                
                /* 确保长度不包含CRC，并且合法 */
                if (frameLength > 4) { /* 减去CRC长度4字节 */
                    frameLength -= 4;
                }
            }
            
            /* 确保长度合法 */
            if (frameLength > 14 && frameLength <= LINKLAYER_MAX_FRAME_SIZE) { /* 至少包含MAC头(14字节) */
                /* 更新接收计数 */
                g_linkLayerComm.rxCount++;
                
                /* 如果注册了回调函数，则调用回调 */
                if (g_linkLayerComm.rxCallback != NULL) {
                    /* 传递接收到的数据(跳过MAC头) */
                    uint32 dataLength = frameLength - 14;
                    g_linkLayerComm.rxCallback(&rxBuffer[14], dataLength);
                }
            }
            
            /* 释放接收缓冲区 */
            IfxGeth_Eth_freeReceiveBuffer(g_linkLayerComm.gethDriver, IfxGeth_RxDmaChannel_0);
        }
    }
    
    /* 清除接收中断标志 */
    IfxGeth_dma_clearInterruptFlag(g_linkLayerComm.gethDriver->gethSFR, 
                                  IfxGeth_DmaChannel_0, 
                                  IfxGeth_DmaInterruptFlag_receiveInterrupt);
}

/**
 * \brief 获取链路层通信状态
 * \return 链路层通信状态指针
 */
LinkLayerComm* LinkLayerComm_getState(void)
{
    return &g_linkLayerComm;
}